﻿//========================================================= 
/**@file CommandService.h
 * @brief 基于命令工作方式的驱动服务
 * 
 * @date 2017-10-27   12:12:16
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_COMMANDSERVICE_H_
#define _LIBZHOUYB_COMMANDSERVICE_H_
//--------------------------------------------------------- 
#include "../CommandAsyncWorker.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
namespace async {
//--------------------------------------------------------- 
/**
 * @brief 模块接口
 * @date 2017-11-01 12:09
 */
struct ICommandModule
{
    /// 处理消息
    virtual bool OnMessage(const char* msg, shared_obj<StringArguments>& arg) = 0;
};
//--------------------------------------------------------- 
/**
 * @brief 服务接口
 * @date 2017-10-27 12:24
 */
struct ICommandService
{
    /// 发送消息
    virtual bool Post(Ref<ICommandModule> sender,  const char* msg, shared_obj<StringArguments>& arg) = 0;
};
//--------------------------------------------------------- 
/**
 * @brief 默认的命令模块
 * @date 2017-10-27 15:36
 */
class CommandModule : public CommandAsyncDispatcher, public ICommandModule
{
protected:
    Ref<ICommand> _callback;
    Ref<ICommandService> _service;
    inline bool Post(const char* msg, shared_obj<StringArguments>& arg)
    {
        return _service->Post(*this, msg, arg);
    }
    LC_CMD_METHOD(Callback)
    {
        boost::unique_lock<boost::mutex> lock(CommandAsyncDispatcher::_mutex);
        CommandTaskExecutor::RefTask task = CommandTaskExecutor::Task(arg);
        if(task == NULL)
            return false;
        TaskDescription* refTask = const_cast<TaskDescription*>(task);
        // 抛出Over事件
        const char TASK_NAME[] = "Task::Name";
        string taskOverName = arg[TASK_NAME].To<string>();
        taskOverName += "OVER";
        return Post(taskOverName.c_str(), refTask->Result);
    }
public:
    CommandModule() : CommandAsyncDispatcher()
    {
        _callback = _MakeCMD(CommandModule, Callback);
    }
    virtual ~CommandModule() {}
    inline void Set(Ref<ICommandService> svr)
    {
        _service = svr;
    }
    /// 处理消息
    virtual bool OnMessage(const char* msg, shared_obj<StringArguments>& arg)
    {
        return CommandAsyncDispatcher::TryAsync(msg, arg, _callback);
    }
};
//--------------------------------------------------------- 
/**
 * @brief 命令驱动服务
 * @date 2017-10-27 15:07
 */
class CommandService : public LoggerBehavior, public ICommandService, public RefObject
{
protected:
    /// 模块
    MapArguments<string, CommandModule*> _service;
    /// 消息路由配置(1对N)
    MapArguments<string, list_t<string> > _msg;
    /// 异步锁
    boost::mutex _mutex;
    /// 根据名称获取指定的模块
    CommandModule* _GetModule(const char* name)
    {
        MapArguments<string, CommandModule*>::EnumeratorType enumer = _service.GetEnumerator();
        while(enumer.MoveNext())
        {
            if(StringConvert::Compare(enumer.Current().Key.c_str(), name))
                return enumer.Current().Value;
        }
        return NULL;
    }
public:
    CommandService() {}
    /**
     * @brief 新增模块,如果有相同名的模块则进行替换
     * @date 2017-10-27 15:09
     */
    template<class T>
    T& New(const char* module, bool* pIsExist = NULL)
    {
        string name = _strput(module);
        CommandModule* pWorker = NULL;
        if(!_service.Get(name, pWorker))
        {
            pWorker = new T();
            pWorker->Set(*this);
            _service.Put(name, pWorker);
        }
        return (*pWorker);
    }
    ///  派发消息
    bool OnMSG(const char* msg, shared_obj<StringArguments>& arg)
    {
        size_t index = StringConvert::IndexOf(msg, '.');
        ByteArray name(msg);
        ByteBuilder module;
        ByteArray cmdName;
        module = name.SubArray(0, index);
        cmdName = name.SubArray(index + 1);

        Ref<CommandModule> pModule = _GetModule(module.GetString());
        if(pModule.IsNull())
            return false;
        return pModule->OnMessage(cmdName.GetString(), arg);
    }
    virtual bool Post(Ref<ICommandModule> sender, const char* msg, shared_obj<StringArguments>& arg)
    {
        boost::unique_lock<boost::mutex> lock(_mutex);

        // 检查模块是否存在
        string name = "";
        if(sender.IsNull())
        {
            bool isContains = false;
            MapArguments<string, CommandModule*>::EnumeratorType enumer = _service.GetEnumerator();
            while(enumer.MoveNext())
            {
                CommandModule* pWorker = enumer.Current().Value;
                if(sender == (*pWorker))
                {
                    name = enumer.Current().Key;
                    isContains = true;
                    break;
                }
            }
            if(!isContains)
                return false;
            name += ".";
        }
        name += _strput(msg);

        // 在消息列表中查找需要触发的消息并依次派发消息
        MapArguments<string, list_t<string> >::EnumeratorType msgEnumer = _msg.GetEnumerator();
        bool isHandled = false;
        while(msgEnumer.MoveNext())
        {
            if(StringConvert::Compare(msgEnumer.Current().Key.c_str(), name.c_str()))
            {
                list_t<string>::iterator itr;
                for(itr = msgEnumer.Current().Value.begin();
                    itr != msgEnumer.Current().Value.end();
                    ++itr)
                {
                    isHandled = true;
                    OnMSG(itr->c_str(), arg);
                }
                break;
            }
        }
        return isHandled;
    }
    /**
     * @brief 注册消息
     * @date 2017-11-27 09:39
     * 
     * @param [in] msg 需要绑定的消息
     * @param [in] router 需要触发的消息
     * 
     * @return size_t 返回注册的消息数目
     */
    size_t BindMSG(const char* msg, const char* router)
    {
        list_t<string>* pMap = NULL;
        if(_msg.Contains(msg))
        {
            pMap = &_msg.Get(msg);
        }
        else
        {
            pMap = &_msg.Put(msg);
        }
        return StringHelper::Split(router, *pMap, ';');
    }
    /**
     * @brief 启用日志
     * @date 2017-11-27 09:36
     * 
     * @param [in] logdir 日志的输出目录
     */
    bool EnableLOG(const char* logdir)
    {
        return true;
    }
    /// 禁用日志
    bool DisableLOG()
    {
        return true;
    }
    /// 启动服务
    void Run()
    {
        MapArguments<string, CommandModule*>::EnumeratorType enumer = _service.GetEnumerator();
        CommandModule* pWorker = NULL;
        while(enumer.MoveNext())
        {
            pWorker = enumer.Current().Value;
            
        }
    }
    /// 停止服务
    void Stop()
    {
    }
    /// 删除指定模块
    bool Remove(const char* module)
    {
        MapArguments<string, CommandModule*>::EnumeratorType enumer = _service.GetEnumerator();
        CommandModule* pWorker = NULL;
        ByteArray sName(module);
        while(enumer.MoveNext())
        {
            if(StringConvert::Compare(sName, enumer.Current().Key.c_str()))
            {
                pWorker = enumer.Current().Value;
                pWorker->Cancel();
                delete pWorker;

                enumer.Remove();
                return true;
            }
        }
        return false;
    }
    /// 删除所有模块
    void Remove()
    {
        MapArguments<string, CommandModule*>::EnumeratorType enumer = _service.GetEnumerator();
        CommandModule* pWorker = NULL;
        while(enumer.MoveNext())
        {
            pWorker = enumer.Current().Value;
            pWorker->Cancel();
            delete pWorker;
        }
        _service.Clear();
        _msg.Clear();
    }
};
//--------------------------------------------------------- 
} // namespace async
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_COMMANDSERVICE_H_
//========================================================= 